package com.yxjx.duoxue;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import com.yxjx.duoxue.utils.Utils;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

public class AppErrorHandler implements UncaughtExceptionHandler{

	private Context mContext;
	private Thread.UncaughtExceptionHandler mDefaultHandler;
	private static AppErrorHandler sInstance = new AppErrorHandler();
	
	
	private HashMap<String, String> mDeviceInfos = new HashMap<String, String>();
	
	private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
	private YxApplication mApplication;  
	
	public static AppErrorHandler getInstance() {
		if (sInstance == null) {
			sInstance = new AppErrorHandler();
		}
		return sInstance;
	}
	
	private AppErrorHandler() {
	}
	
	public void init(Context context, YxApplication app) {
		mContext = context;
		mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
		mApplication = app;
		Thread.setDefaultUncaughtExceptionHandler(this);
	}

	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		if (handleException(ex)) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			Log.e("CMM7", "uncaught exception");
		}
		System.exit(1);
	}
	
	private boolean handleException(Throwable ex) {
		if (ex == null) {
			return false;
		}
		new Thread() {
			@Override
			public void run() {
				Looper.prepare();
				Toast.makeText(mContext, R.string.sorry_to_exit, Toast.LENGTH_SHORT).show();
				Looper.loop();
				System.exit(1);
			}
		}.start();
		
		collectDeviceInfo();
		if (!Config.RELEASE_VERSION) {
			saveErrorFile(ex);
		}
		return true;
	}

	private String saveErrorFile(Throwable ex) {
		StringBuilder sb = new StringBuilder();
		for (String key : mDeviceInfos.keySet()) {
			sb.append(key + mDeviceInfos.get(key) + "\n");
		}
		
		Writer writer = new StringWriter();
		PrintWriter printWriter = new PrintWriter(writer);
		ex.printStackTrace(printWriter);
		
		Throwable cause = ex.getCause();
		while (cause != null) {
			cause.printStackTrace(printWriter);
			cause = cause.getCause();
		}
		printWriter.close();
		
		String result = writer.toString();
		sb.append(result);
		
		// write file
		try {
			long timestamp = System.currentTimeMillis();
			String time = formatter.format(new Date());
			String fileName = "yxjx_crash_" + time + ".txt";
			File mCache = new File(Environment.getExternalStorageDirectory(), "yxjx_cache");
	    	if (!mCache.exists()) {
	    		mCache.mkdirs();
	    	}
			File file = new File(mCache, fileName);
			FileOutputStream fos = new FileOutputStream(file);
			fos.write(sb.toString().getBytes());
			return fileName;
		} catch (IOException e) {
			Log.e(Yx.TAG, "write crash file exception");
		}
		return null;
	}
	

	private void collectDeviceInfo() {
		mDeviceInfos.put("occur time: ", Utils.getTimeStamp());
//		mDeviceInfos.put("phone num: ", UserInfoUtil.getCurrentUserPhoneNum(mContext));
		mDeviceInfos.put("app versoin name: ", Utils.getAppVersionName(mContext));
		mDeviceInfos.put("app hardware info: ", Utils.getHardwareInfo(mContext));
		mDeviceInfos.put("network info: ", Utils.getNetworkInfo(mContext));
		mDeviceInfos.put("software info: ", Utils.getSoftwareInfo());
	}

}
